home *** CD-ROM | disk | FTP | other *** search
Text File | 2003-02-23 | 27.1 KB | 1,009 lines |
- //--------------------------------------------------------------------------
- //
- // Copyright (c) 2002, Colin Granville
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or
- // without modification, are permitted provided that the following
- // conditions are met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- //
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following
- // disclaimer in the documentation and/or other materials
- // provided with the distribution.
- //
- // * The name Colin Granville may not be used to endorse or promote
- // products derived from this software without specific prior
- // written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- // OF THE POSSIBILITY OF SUCH DAMAGE.
- //
- //--------------------------------------------------------------------------
-
- #include "DrawOutputDevice.h"
- #include "GuiDrawFileSprite.h"
- #include "GuiDrawFileFonts.h"
- #include "swis.h"
- #include "ColourSpace.h"
- #include "GfxState.h"
- #include "iostream.h"
- #include <math.h>
- #include "guilib:gfx.h"
- #include "GfxFont.h"
-
- class Convert
- {
- public:
- Convert(double* matrix) : ctm(matrix) {}
-
- void userToDev(double x1, double y1, int& x2, int& y2)
- {
- x2 = (int)(ctm[0] * x1 + ctm[2] * y1 + ctm[4] + 0.5);
- y2 = (int)(ctm[1] * x1 + ctm[3] * y1 + ctm[5] + 0.5);
- }
- private:
- double* ctm;
- };
-
- //*****************************************************************
- //*****************************************************************
- //*****************************************************************
-
- DrawOutputDevice::DrawOutputDevice()
- : draw("PDF"),
- path(draw),
- text(draw),
- noImages(0),
- noText(0),
- noType3Fonts(0),
- noDrawings(0)
- {
- }
-
- //*****************************************************************
-
- DrawOutputDevice::~DrawOutputDevice() {}
-
- //*****************************************************************
-
- GBool DrawOutputDevice::upsideDown() {return gFalse;}
- GBool DrawOutputDevice::useDrawChar() {return gTrue;}
- GBool DrawOutputDevice::interpretType3Chars() {return !noType3Fonts;}
-
- //*****************************************************************
-
- void DrawOutputDevice::startPage(int /*pageNum*/, GfxState *state)
- {
- draw.reopen();
- Convert cvt(state->getCTM());
- cvt.userToDev(state->getX1(),state->getY1(),bounds.xmin,bounds.ymin);
- cvt.userToDev(state->getX2(),state->getY2(),bounds.xmax,bounds.ymax);
- clipbox.init(bounds);
-
- if (font.getUsedFont(1))
- {
- GuiDrawFileFonts fonts(draw);
- const char* fontname;
- int index;
- fonts.start();
- for (index=1;fontname=font.getUsedFont(index),fontname;index++) fonts.add(index,fontname);
- fonts.end();
- }
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::endPage()
- {
- draw.endCurrentObject();
- draw.setBBox(bounds);
- font.clear();
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::saveState(GfxState*)
- {
- clipbox.push();
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::restoreState(GfxState* state)
- {
- clipbox.pop();
- updateAll(state);
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::setClip(GfxState* state, int isEo)
- {
- // a bodge but its better than nothing
-
- GfxPath& gfx_path=*state->getPath();
- if (gfx_path.getNumSubpaths()==0) return;
-
- int i;
- int pathSize=0;
- for (i=0;i<gfx_path.getNumSubpaths();i++)
- {
- GfxSubpath& subpath= *(gfx_path.getSubpath(i));
- int number_of_points=subpath.getNumPoints();
- if (number_of_points<2) continue;
- int n;
- pathSize+=3;
- for (n=1;n<number_of_points;n++)
- {
- if (subpath.getCurve(n))
- {
- pathSize+=7; n+=2;
- }
- else
- {
- pathSize+=3;
- }
- }
- if (subpath.isClosed()) pathSize++;
- }
-
- if (pathSize)
- {
- int* path=new int[pathSize+4];
- if (!path) return;
-
- int pos=0;
- path[pos++]=pathSize+4;
- path[pos++]=isEo;
- int x,y;
- Convert cvt(state->getCTM());
-
- for (i=0;i<gfx_path.getNumSubpaths();i++)
- {
- GfxSubpath& subpath= *(gfx_path.getSubpath(i));
- int number_of_points=subpath.getNumPoints();
- if (number_of_points<2) continue;
-
- path[pos++]=2;
- cvt.userToDev(subpath.getX(0),subpath.getY(0),x,y);
- path[pos++]=x; path[pos++]=y;
-
- int n;
- for (n=1;n<number_of_points;n++)
- {
- if (subpath.getCurve(n))
- {
- path[pos++]=6;
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- path[pos++]=x; path[pos++]=y; n++;
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- path[pos++]=x; path[pos++]=y; n++;
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- path[pos++]=x; path[pos++]=y;
- }
- else
- {
- path[pos++]=8;
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- path[pos++]=x; path[pos++]=y;
- }
- }
- if (subpath.isClosed()) path[pos++]=5;
- }
- path[pos]=0;
- clipbox.setPath(path);
- }
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::clip(GfxState* state)
- {
- setClip(state,0);
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::eoClip(GfxState* state)
- {
- setClip(state,1);
- }
-
- //*****************************************************************
- void DrawOutputDevice::updateLineJoin(GfxState* state)
- {
- pathState.setJoin(state->getLineJoin());
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::updateLineCap(GfxState* state)
- {
- pathState.setStartCap(state->getLineCap());
- pathState.setEndCap(pathState.getStartCap());
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::updateLineWidth(GfxState* state)
- {
- pathState.setOutlineWidth((unsigned int)state->getTransformedLineWidth());
- }
-
- //*****************************************************************
-
- inline unsigned int getColour(GfxRGB& rgb)
- {
- unsigned int r=(unsigned int)(rgb.r*256.0);
- if (r>=255) r=255;
- unsigned int g=(unsigned int)(rgb.g*256.0);
- if (g>=255) g=255;
- unsigned int b=(unsigned int)(rgb.b*256.0);
- if (b>255) b=255;
- return (r<<8) | (g<<16) | (b<<24);
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::updateFillColor(GfxState* state)
- {
- GfxRGB rgb;
- state->getFillRGB(&rgb);
- pathState.setFillColour(getColour(rgb));
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::updateStrokeColor(GfxState*state)
- {
- GfxRGB rgb;
- state->getStrokeRGB(&rgb);
- pathState.setOutlineColour(getColour(rgb));
- }
-
- //*****************************************************************
-
- bool DrawOutputDevice::doPath(GfxState* state)
- {
- int i;
- GfxPath& gfx_path=*state->getPath();
- int mask;
- Convert cvt(state->getCTM());
- for (i=0;i<gfx_path.getNumSubpaths();i++)
- {
- GfxSubpath& subpath= *(gfx_path.getSubpath(i));
- int number_of_points=subpath.getNumPoints();
- if (number_of_points<2) continue;
-
- path.moveTo();
- int x,y;
- cvt.userToDev(subpath.getX(0),subpath.getY(0),x,y);
- mask=clipbox.clip(x,y);
- path.point(x,y);
- int n;
- for (n=1;n<number_of_points;n++)
- {
- if (subpath.getCurve(n))
- {
- path.bezierTo();
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- mask &= clipbox.clip(x,y);
- path.point(x,y); n++;
-
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- mask &= clipbox.clip(x,y);
- path.point(x,y); n++;
-
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- mask &= clipbox.clip(x,y);
- path.point(x,y);
- }
- else
- {
- path.drawTo();
- cvt.userToDev(subpath.getX(n),subpath.getY(n),x,y);
- mask &= clipbox.clip(x,y);
- path.point(x,y);
- }
- }
- if (subpath.isClosed()) path.closeSubPath();
- }
-
- // removal of paths outside clipbox
- // mask is nonzero if all points have an x or y clipped on the same side
-
- return mask==0;
- }
-
- //*****************************************************************
-
- //----- path painting
- void DrawOutputDevice::stroke(GfxState* state)
- {
- if (noDrawings) return;
-
- if (pathState.getOutlineColour() == GuiDrawFilePathState::OFF ||
- !state->isPath()) return;
-
- unsigned int fill_colour = pathState.getFillColour();
- pathState.setFillColour(GuiDrawFilePathState::OFF);
- path.start();
-
- double* pattern;
- int length;
- double start;
- state->getLineDash(&pattern,&length,&start);
- pathState.setDashPattern(length);
- if (length)
- {
- path.dashPattern((int)state->transformWidth(start),length);
- for (;length;length--) path.dashElement((unsigned int)state->transformWidth(*pattern++));
- }
-
- if (doPath(state)) path.end(pathState); //if you don't end a path it's ignored
-
- pathState.setDashPattern();
- pathState.setFillColour(fill_colour);
- }
-
- //*****************************************************************
-
-
- ostream& operator<<(ostream& out,const GuiBBox& box)
- {
- out << box.xmin << ' ' << box.ymin << ' ' << box.xmax << ' ' << box.ymax;
- return out;
- }
-
- inline bool contains(const GuiBBox a,const GuiBBox& b)
- {
- return (b.xmin>=a.xmin && b.ymin>=a.ymin &&
- b.xmax<=a.xmax && b.ymax<=a.ymax);
- }
-
- inline void clipTo(Clip& clipbox,int x,int y,int& ox, int& oy)
- {
- clipbox.clip(x,y);
- ox=x;
- oy=y;
- }
-
- bool DrawOutputDevice::doRectanglePath(GfxState* state)
- {
- if (!(clipbox.getPath() || clipbox.getBBox() )) return 0;
- GfxPath *gfxpath=state->getPath();
-
- if (gfxpath->getNumSubpaths()==1 &&
- gfxpath->getSubpath(0)->getNumPoints() == 5)
- {
- GfxSubpath* subpath = gfxpath->getSubpath(0);
- struct {int x,y; } pt[5];
- Convert cvt(state->getCTM());
- for (int i=0;i<5;i++)
- {
- cvt.userToDev(subpath->getX(i),subpath->getY(i),pt[i].x,pt[i].y);
- }
- GuiBBox box;
- box.xmin=pt[0].x;
- box.xmax=pt[2].x;
- box.ymin=pt[0].y;
- box.ymax=pt[2].y;
-
- if (!( box.xmin==pt[4].x && box.ymin==pt[4].y &&
- ((box.xmin==pt[1].x && box.ymin == pt[3].y &&
- box.xmax==pt[3].x && box.ymax == pt[1].y) ||
- (box.xmin==pt[3].x && box.ymin == pt[1].y &&
- box.xmax==pt[1].x && box.ymax == pt[3].y))
- )) return 0;
-
- if (box.xmin>box.xmax) {int temp=box.xmin;box.xmin=box.xmax;box.xmax=temp;}
- if (box.ymin>box.ymax) {int temp=box.ymin;box.ymin=box.ymax;box.ymax=temp;}
-
- if (!contains(box,*clipbox.getBBox()) )
- {
- if (!contains(*clipbox.getBBox(),box) ) return 0;
- path.moveTo();
- path.point(pt[0].x,pt[0].y);
- path.drawTo();
- path.point(pt[1].x,pt[1].y);
- path.drawTo();
- path.point(pt[2].x,pt[2].y);
- path.drawTo();
- path.point(pt[3].x,pt[3].y);
- path.closeSubPath();
- return 1;
- }
-
- int x,y;
- for (const int* p=clipbox.getPath()+2;*p!=0;p++)
- {
- switch (*p)
- {
- case 2: path.moveTo();
- clipTo(clipbox,p[1],p[2],x,y);
- path.point(x,y);
- p+=2;
- break;
- case 8: path.drawTo();
- clipTo(clipbox,p[1],p[2],x,y);
- path.point(x,y);
- p+=2;
- break;
- case 5: path.closeSubPath();
- break;
- case 6: path.bezierTo();
- clipTo(clipbox,p[1],p[2],x,y);
- path.point(x,y);
- clipTo(clipbox,p[3],p[4],x,y);
- path.point(x,y);
- clipTo(clipbox,p[5],p[6],x,y);
- path.point(x,y);
- p+=6;
- break;
- }
- }
-
- return 1;
- }
- return 0;
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::fill(GfxState* state)
- {
- if (noDrawings) return;
-
- if (pathState.getFillColour() == GuiDrawFilePathState::OFF) return;
- unsigned int outline_colour = pathState.getOutlineColour();
- pathState.setOutlineColour(GuiDrawFilePathState::OFF);
- pathState.setWindingRule(GuiDrawFilePathState::NON_ZERO);
- path.start();
- if (doRectanglePath(state) || doPath(state)) path.end(pathState);
- pathState.setOutlineColour(outline_colour);
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::eoFill(GfxState* state)
- {
- if (noDrawings) return;
-
- if (pathState.getFillColour() == GuiDrawFilePathState::OFF) return;
- unsigned int outline_colour = pathState.getOutlineColour();
- pathState.setOutlineColour(GuiDrawFilePathState::OFF);
- pathState.setWindingRule(GuiDrawFilePathState::EVEN_ODD);
- path.start();
- if (doRectanglePath(state) || doPath(state)) path.end(pathState);
-
- pathState.setOutlineColour(outline_colour);
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::updateFont(GfxState *state)
- {
- updateRender(state);
- font.set(*state);
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::updateRender(GfxState *state)
- {
- }
- //*****************************************************************
-
- static Unicode* getLigature(Unicode u,int &len)
- {
- static Unicode ff[]= {'f','f'};
- static Unicode ffi[]= {'f','f','i'};
- static Unicode ffl[]= {'f','f','l'};
- switch (u)
- {
- case 0xFB00: len=2;return ff;
- case 0xFB03: len=3;return ffi;
- case 0xFB04: len=3;return ffl;
- }
- return 0;
- }
- void DrawOutputDevice::drawChar(GfxState *state, double x, double y,
- double dx, double dy,
- double originX, double originY,
- CharCode code, Unicode *uni, int uLen)
- {
- if (noText || uLen<=0) return;
-
- if (state->getRender() & 1)
- {
- font.foreColour = pathState.getOutlineColour();
- font.backColour = (font.foreColour==0xffffff00 ? 0 : 0xffffff00);
- }
- else
- {
- font.foreColour = pathState.getFillColour();
- font.backColour = (font.foreColour==0xffffff00 ? 0 : 0xffffff00);
- }
- Unicode* u=uni;
- unsigned int ch=font.getChar(u[0]);
- if (!ch) u=getLigature(u[0],uLen);
- if (u)
- {
- text.start();
- double width=0;
- int i;
- for (i=0;i<uLen;i++)
- {
- ch=font.getChar(u[i]);
- if (ch)
- {
- width+=font.getCharWidth(ch);
- text.put(ch);
- }
- }
- Convert cvt(state->getCTM());
- cvt.userToDev(x,y,font.x,font.y);
- font.setCharMatrix(originX,width);
- text.end(font,font.getHandle());
- }
- }
-
- //*****************************************************************
-
- void DrawOutputDevice::drawString(GfxState *state, GString *s)
- {
- if (noText) return;
-
- if (state->getRender() & 1)
- {
- font.foreColour = pathState.getOutlineColour();
- font.backColour = (font.foreColour==0xffffff00 ? 0 : 0xffffff00);
- }
- else
- {
- font.foreColour = pathState.getFillColour();
- font.backColour = (font.foreColour==0xffffff00 ? 0 : 0xffffff00);
- }
-
- GfxFont* fnt=state->getFont();
- if (!fnt) return;
-
- double x=0;
- char* p=s->getCString();
- int len= s->getLength();
- Unicode uni[8];
- int uLen;
- CharCode code;
- double xtotal=0;
- double dummy;
- int nChars=0;
- int nSpaces=0;
- double width=0;
-
- Convert cvt(state->getCTM());
- cvt.userToDev(state->getCurX(),state->getCurY(),font.x,font.y);
- text.start();
- while (len > 0)
- {
- Unicode* u=uni;
- int n = fnt->getNextChar(p, len, &code,
- u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
- &x, &dummy, &dummy, &dummy);
-
- unsigned int ch=font.getChar(u[0]);
- if (!ch) u=getLigature(u[0],uLen);
-
- if (u)
- {
- int i;
- for (i=0;i<uLen;i++)
- {
- ch=font.getChar(u[i]);
- if (ch)
- {
- text.put(ch);
- width+=font.getCharWidth(ch);
- }
- }
- }
- xtotal+=x;
- if (n == 1 && *p == ' ')
- {
- ++nSpaces;
- }
- ++nChars;
- p += n;
- len -= n;
- }
- if (nChars && state->getCharSpace()!=0)
- xtotal+=nChars * state->getCharSpace()/state->getFontSize();
- if (nSpaces && state->getWordSpace()!=0)
- xtotal+=nSpaces * state->getWordSpace()/state->getFontSize();
- font.setCharMatrix(xtotal,width);
- text.end(font,font.getHandle());
- }
- //*****************************************************************
-
- //scales draw units dpi to image dpi * (1<<16)
- #define IMAGE_SCALE_FACTOR 128
-
- class ReverseSamples
- {
- public:
- ReverseSamples();
- void setbpc(int bpc) {
- if (bpc>4) b=b8;
- else if (bpc>2) b=b4;
- else if (bpc>1) b=b2;
- else b=b1;
- }
- unsigned int sample(unsigned char c) {return b[c];}
- private:
- unsigned char b1[256];
- unsigned char b2[256];
- unsigned char b4[256];
- unsigned char b8[256];
- unsigned char* b;
-
- };
-
- ReverseSamples::ReverseSamples()
- {
- unsigned int i;
- b=b8;
- for (i=0;i<256;i++)
- {
- b1[i] = ((i & 1) << 7) |
- ((i & 2) << 5) |
- ((i & 4) << 3) |
- ((i & 8) << 1) |
- ((i & 16) >> 1) |
- ((i & 32) >> 3) |
- ((i & 64) >> 5) |
- ((i & 128) >> 7);
-
- b2[i] = ((i & 3) << 6) |
- ((i & 0xc)<< 2) |
- ((i & 0x30) >> 2) |
- ((i & 0xC0) >> 6);
-
- b4[i] = ((i & 0xf) << 4) |
- ((i & 0xf0) >> 4);
- b8[i]=i;
- }
- }
-
- ReverseSamples reverse;
-
- //*****************************************************************
-
- void DrawOutputDevice::drawImageMask(GfxState *state, Object* /*ref*/, Stream *str,
- int width, int height, GBool invert,
- GBool /*inlineImg*/)
- {
- if (width==0 || height==0 || noImages) return;
- str->reset();
-
- GuiDrawFileSprite sprite(draw);
- sprite.start(width,height,1);
- sprite.put(pathState.getFillColour());
- sprite.put(pathState.getFillColour());
- sprite.put(0);
- sprite.put(0);
-
- unsigned int bits=width-1;
- int h,w;
- sprite.startImage();
- for (h=height;h;h--)
- {
- for (w=bits;w>=0;w-=32) sprite.put(0);
- }
- sprite.startMask();
- reverse.setbpc(1);
- unsigned int n;
- // cerr << bits << ' ' << width << ' ' << height << endl;
- unsigned int invertbits= (invert ? 0:-1u);
- for (h=height;h;h--)
- {
- for (w=bits;w>=0;w-=32)
- {
- n=reverse.sample(str->getChar());
- if (w>=8) n|=(reverse.sample(str->getChar()) << 8);
- if (w>=16) n|=(reverse.sample(str->getChar()) << 16);
- if (w>=24) n|=(reverse.sample(str->getChar()) << 24);
- sprite.put(n^invertbits);
- }
- }
-
-
- { // calculate transform matrix and bounds
- GuiBBox bounds;
-
- double* mat=state->getCTM();
- Convert cvt(mat);
-
- GuiTransform matrix;
- matrix.m0 = (int)( mat[0] * IMAGE_SCALE_FACTOR /width);
- matrix.m1 = (int)( mat[1] * IMAGE_SCALE_FACTOR /width);
- matrix.m2 = (int)( mat[2] * IMAGE_SCALE_FACTOR /height);
- matrix.m3 = (int)( mat[3] * IMAGE_SCALE_FACTOR /height);
-
- Boundary_start(bounds);
- int x,y;
- cvt.userToDev(0.0,0.0,x,y);
- matrix.m4 = x;
- matrix.m5 = y;
- Boundary_point(bounds,x,y);
- cvt.userToDev(0.0,1.0,x,y);
- Boundary_point(bounds,x,y);
- cvt.userToDev(1.0,1.0,x,y);
- Boundary_point(bounds,x,y);
- cvt.userToDev(1.0,0.0,x,y);
- Boundary_point(bounds,x,y);
- sprite.end(matrix,bounds);
- }
- }
- //*****************************************************************
-
- void DrawOutputDevice::drawImage(GfxState *state, Object * /*ref*/, Stream *str,
- int width, int height, GfxImageColorMap *colorMap,
- int */*maskColors*/, GBool /*inlineImg*/)
- {
- if (width==0 || height==0 || noImages) return;
-
-
- int bpc = colorMap->getBits();
- int ncomps = colorMap->getNumPixelComps();
-
- str->reset();
-
- ColourSpace* colourSpace=makeColourSpace(colorMap->getColorSpace());
- GuiDrawFileSprite sprite(draw);
- // cerr << "mode " << colorMap->getColorSpace()->getMode() << endl;
- // cerr << bpc << ' ' << ncomps << ' ' << width << ' ' << height << endl;
- // cerr << "decode " << colorMap->getDecodeLow(0) << ' ' << colorMap->getDecodeHigh(0) << endl;
- if (ncomps == 1 &&
- (bpc<8 || (bpc==8 && width*height*3>2048) ) )
- {
- int step;
- switch (bpc)
- {
- case 1: step=0xff;break;
- case 2: step=0x55;break;
- case 4: step=0x11;break;
- case 8: step=1; break;
- default: delete colourSpace;return; //illegal bpc
- }
- sprite.start(width,height,bpc);
- if (draw.hasFailed())
- {
- delete colourSpace;
- return;
- }
-
- if (colorMap->getColorSpace()->getMode()==csIndexed)
- {
- int col;
- int i;
- for (col=0,i=0;i<256;i+=step,col++)
- {
- unsigned int n=colourSpace->getRGB((unsigned char*)&col);
- // cerr << n << endl;
- sprite.put(n);
- sprite.put(n);
- }
- }
- else
- {
- unsigned int invert=(colorMap->getDecodeLow(0) > colorMap->getDecodeHigh(0) ? 0xffffff00 : 0);
- int i;
- for (i=0;i<256;i+=step)
- {
- unsigned int n=colourSpace->getRGB((unsigned char*)&i)^invert;
- // cerr << n << endl;
- sprite.put(n);
- sprite.put(n);
- }
- }
-
- sprite.startImage();
- reverse.setbpc(bpc);
- unsigned int bits=width*bpc-1;
- int h,w;
- unsigned int n;
- for (h=height;h;h--)
- {
- for (w=bits;w>=0;w-=32)
- {
- n=reverse.sample(str->getChar());
- if (w>=8) n|=(reverse.sample(str->getChar()) << 8);
- if (w>=16) n|=(reverse.sample(str->getChar()) << 16);
- if (w>=24) n|=(reverse.sample(str->getChar()) << 24);
- sprite.put(n);
- }
- }
- }
- else if (bpc == 8)
- {
- sprite.start(width,height,32);
- if (draw.hasFailed())
- {
- delete colourSpace;
- return;
- }
- sprite.startImage();
- unsigned char n[8];
- int i;
- int c;
- int comps=ncomps;
- if (comps>8) comps=8; //shouldn't happen but you never know
- for (i=width*height;i;i--)
- {
- for (c=0;c<comps;c++) n[c] = str->getChar();
- sprite.put(colourSpace->getRGB(n)>>8);
- }
- }
- else
- {
- static unsigned char col1[] = {0,0xff};
- static unsigned char col2[] = {0,0x55,0xaa,0xff};
- static unsigned char col4[] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
- 0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff};
- unsigned char* colour;
-
- sprite.start(width,height,32);
- if (draw.hasFailed())
- {
- delete colourSpace;
- return;
- }
- sprite.startImage();
- int shift;
- switch (bpc)
- {
- case 1: shift=1;colour=col1;break;
- case 2: shift=2;colour=col2;break;
- default: shift=4;colour=col4;break;
- }
- unsigned char n[8];
- int c;
- int comps=ncomps;
- if (comps>8) comps=8; //shouldn't happen but you never know
- int buffer;
- int h,w;
-
- for (h=height;h;h--)
- {
- buffer=0x1000000;
- for (w=width;w;w--)
- {
- for (c=0;c<comps;c++)
- {
- if (buffer >= 0x1000000) { buffer=str->getChar(); buffer |= 0x10000;}
- buffer <<=shift;
- n[c]= colour[(buffer >> 8) & 0xf];
- }
- sprite.put(colourSpace->getRGB(n)>>8);
- }
- }
- }
-
- delete colourSpace;
-
- { // calculate transform matrix and bounds
- GuiBBox bounds;
-
- double* mat=state->getCTM();
- Convert cvt(mat);
-
- GuiTransform matrix;
- matrix.m0 = (int)( mat[0] * IMAGE_SCALE_FACTOR /width);
- matrix.m1 = (int)( mat[1] * IMAGE_SCALE_FACTOR /width);
- matrix.m2 = (int)( mat[2] * IMAGE_SCALE_FACTOR /height);
- matrix.m3 = (int)( mat[3] * IMAGE_SCALE_FACTOR /height);
- Boundary_start(bounds);
- int x,y;
- cvt.userToDev(0.0,0.0,x,y);
- matrix.m4 = x;
- matrix.m5 = y;
- Boundary_point(bounds,x,y);
- cvt.userToDev(0.0,1.0,x,y);
- Boundary_point(bounds,x,y);
- cvt.userToDev(1.0,1.0,x,y);
- Boundary_point(bounds,x,y);
- cvt.userToDev(1.0,0.0,x,y);
- Boundary_point(bounds,x,y);
-
- if (clipbox.getPath()) sprite.startMaskFill();
- sprite.end(matrix,bounds);
-
- if (draw.hasFailed()) return;
-
- //cerr << "SPRITE" << endl;
- if (clipbox.getPath())
- {
- GuiTransform pathMatrix;
-
- {
- //extend stack so that sprite ptr doesn't move
- char a[256];
-
- //invert matrix
- double m[4], om[4];
- m[0]=((double)matrix.m0)/0x10000;
- m[1]=((double)matrix.m1)/0x10000;
- m[2]=((double)matrix.m2)/0x10000;
- m[3]=((double)matrix.m3)/0x10000;
- double det=1/(m[0]*m[3] - m[1]*m[2]);
- //cerr << "m "<< m[0] <<',' << m[1] <<',' << m[2] <<',' << m[3] << endl;
- om[0]=m[3]*det;
- om[1]=-m[1]*det;
- om[2]=-m[2]*det;
- om[3]=m[0]*det;
- //cerr << "om "<< om[0] <<',' << om[1] <<',' << om[2] <<',' << om[3] << endl;
-
-
- pathMatrix.m0=(int)(om[0]*0x10000);
- pathMatrix.m1=(int)(om[1]*0x10000);
- pathMatrix.m2=(int)(om[2]*0x10000);
- pathMatrix.m3=(int)(om[3]*0x10000);
- pathMatrix.m4=(int)((m[2]*(double)matrix.m5-m[3]*(double)matrix.m4)*det);
- pathMatrix.m5=(int)((m[1]*(double)matrix.m4-m[0]*(double)matrix.m5)*det);
- }
-
- int r1,r2,r3;
- char* spr=sprite.getPtr();
-
- _kernel_oserror* err=_swix(OS_SpriteOp,_INR(0,3) | _OUTR(1,3),0x200+61,spr,spr,0,&r1,&r2,&r3);
- if (err==0)
- {
- _swix(ColourTrans_SetColour,_IN(0)|_INR(3,4),0xff,0,0);
- err=_swix(Draw_Fill,_INR(0,3),clipbox.getPath()+2,0,&pathMatrix,0);
- _swix(OS_SpriteOp,_INR(0,3),0x200+61,r1,r2,r3);
- }
- // cerr << matrix.m0 << ' ' << matrix.m1 << endl;
- // cerr << matrix.m2 << ' ' << matrix.m3 << endl;
- // cerr << matrix.m4 << ' ' << matrix.m5 << endl;
- // cerr <<"xy " << matrix.m4/256 <<',' << matrix.m5/256 << endl;
- // int* p=clipbox.getPath();
- // int i;
- // cerr << "++++++++" << endl;
- // for (i=0;i<p[0]-1;i++)
- // {
- // cerr << p[i];
- // switch (p[i])
- // {
- // case 6: cerr << ' '
- // << p[i+1] << ',' << p[i+2] << ' '
- // << p[i+3] << ',' << p[i+5] << ' '
- // << p[i+5] << ',' << p[i+6];
- // i+=6;
- // break;
- // case 2:
- // case 8: cerr << ' '
- // << p[i+1]/256 << ',' << p[i+2]/256;
- // i+=2;
- // break;
- // }
- // cerr << endl;
- // }
- // cerr << "--------" << endl;
- }
- }
- }
-